mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 05:08:06 +02:00
+ default code now preserves mm registers
* save|restore_standard_registers => save|restore_registers git-svn-id: trunk@8954 -
This commit is contained in:
parent
3a630340be
commit
00d6a03b2c
@ -98,8 +98,8 @@ unit cgcpu;
|
||||
procedure g_overflowcheck(list: TAsmList; const l: tlocation; def: tdef); override;
|
||||
procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
|
||||
|
||||
procedure g_save_standard_registers(list : TAsmList);override;
|
||||
procedure g_restore_standard_registers(list : TAsmList);override;
|
||||
procedure g_save_registers(list : TAsmList);override;
|
||||
procedure g_restore_registers(list : TAsmList);override;
|
||||
|
||||
procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
|
||||
procedure fixref(list : TAsmList;var ref : treference);
|
||||
@ -1842,13 +1842,13 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgarm.g_save_standard_registers(list : TAsmList);
|
||||
procedure tcgarm.g_save_registers(list : TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_entry }
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgarm.g_restore_standard_registers(list : TAsmList);
|
||||
procedure tcgarm.g_restore_registers(list : TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_exit }
|
||||
end;
|
||||
|
@ -339,6 +339,10 @@ unit cpubase;
|
||||
}
|
||||
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_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{ 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.
|
||||
|
@ -39,7 +39,7 @@ unit cgobj;
|
||||
cclasses,globtype,constexp,
|
||||
cpubase,cgbase,cgutils,parabase,
|
||||
aasmbase,aasmtai,aasmdata,aasmcpu,
|
||||
symconst,symbase,symtype,symdef,symtable,rgobj
|
||||
symconst,symtype,symdef,rgobj
|
||||
;
|
||||
|
||||
type
|
||||
@ -462,24 +462,25 @@ unit cgobj;
|
||||
|
||||
@param(usedinproc Registers which are used in the code of this routine)
|
||||
}
|
||||
procedure g_save_standard_registers(list:TAsmList);virtual;
|
||||
procedure g_save_registers(list:TAsmList);virtual;
|
||||
{# This routine is called when generating the code for the exit point
|
||||
of a routine. It should restore all registers which were previously
|
||||
saved in @var(g_save_standard_registers).
|
||||
|
||||
@param(usedinproc Registers which are used in the code of this routine)
|
||||
}
|
||||
procedure g_restore_standard_registers(list:TAsmList);virtual;
|
||||
procedure g_restore_registers(list:TAsmList);virtual;
|
||||
|
||||
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
|
||||
procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);virtual;
|
||||
|
||||
function g_indirect_sym_load(list:TAsmList;const symname: string): tregister;virtual;
|
||||
{ generate a stub which only purpose is to pass control the given external method,
|
||||
{ generate a stub which only purpose is to pass control the given external method,
|
||||
setting up any additional environment before doing so (if required).
|
||||
|
||||
The default implementation issues a jump instruction to the external name. }
|
||||
procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual;
|
||||
|
||||
|
||||
{ initialize the pic/got register }
|
||||
procedure g_maybe_got_init(list: TAsmList); virtual;
|
||||
protected
|
||||
@ -3594,17 +3595,26 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg.g_save_standard_registers(list:TAsmList);
|
||||
procedure tcg.g_save_registers(list:TAsmList);
|
||||
var
|
||||
href : treference;
|
||||
size : longint;
|
||||
r : integer;
|
||||
begin
|
||||
{ Get temp }
|
||||
{ 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
|
||||
inc(size,sizeof(aint));
|
||||
|
||||
{ mm registers }
|
||||
if uses_registers(R_MMREGISTER) then
|
||||
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
|
||||
inc(size,tcgsize2size[OS_VECTOR]);
|
||||
|
||||
tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
|
||||
|
||||
if size>0 then
|
||||
begin
|
||||
tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
|
||||
@ -3620,11 +3630,22 @@ implementation
|
||||
end;
|
||||
include(rg[R_INTREGISTER].preserved_by_proc,saved_standard_registers[r]);
|
||||
end;
|
||||
|
||||
if uses_registers(R_MMREGISTER) then
|
||||
for r:=low(saved_mm_registers) to high(saved_mm_registers) do
|
||||
begin
|
||||
if saved_mm_registers[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_SUBNONE),href,nil);
|
||||
inc(href.offset,tcgsize2size[OS_VECTOR]);
|
||||
end;
|
||||
include(rg[R_MMREGISTER].preserved_by_proc,saved_mm_registers[r]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg.g_restore_standard_registers(list:TAsmList);
|
||||
procedure tcg.g_restore_registers(list:TAsmList);
|
||||
var
|
||||
href : treference;
|
||||
r : integer;
|
||||
@ -3644,6 +3665,21 @@ implementation
|
||||
inc(href.offset,sizeof(aint));
|
||||
freetemp:=true;
|
||||
end;
|
||||
|
||||
if uses_registers(R_MMREGISTER) then
|
||||
for r:=low(saved_mm_registers) to high(saved_mm_registers) do
|
||||
begin
|
||||
if saved_mm_registers[r] in rg[R_MMREGISTER].used_in_proc then
|
||||
begin
|
||||
hreg:=newreg(R_MMREGISTER,saved_mm_registers[r],R_SUBNONE);
|
||||
{ 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);
|
||||
inc(href.offset,tcgsize2size[OS_VECTOR]);
|
||||
freetemp:=true;
|
||||
end;
|
||||
end;
|
||||
|
||||
if freetemp then
|
||||
tg.UnGetTemp(list,current_procinfo.save_regs_ref);
|
||||
end;
|
||||
|
@ -159,6 +159,8 @@
|
||||
GCC source.
|
||||
}
|
||||
saved_standard_registers : array[0..2] of tsuperregister = (RS_EBX,RS_ESI,RS_EDI);
|
||||
|
||||
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.
|
||||
|
@ -86,8 +86,8 @@ unit cgcpu;
|
||||
|
||||
// procedure g_restore_frame_pointer(list : TAsmList);override;
|
||||
// procedure g_return_from_proc(list : TAsmList;parasize : aint);override;
|
||||
procedure g_restore_standard_registers(list:TAsmList);override;
|
||||
procedure g_save_standard_registers(list:TAsmList);override;
|
||||
procedure g_restore_registers(list:TAsmList);override;
|
||||
procedure g_save_registers(list:TAsmList);override;
|
||||
|
||||
// procedure g_save_all_registers(list : TAsmList);override;
|
||||
// procedure g_restore_all_registers(list : TAsmList;const funcretparaloc:TCGPara);override;
|
||||
@ -1410,7 +1410,7 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure Tcg68k.g_save_standard_registers(list:TAsmList);
|
||||
procedure Tcg68k.g_save_registers(list:TAsmList);
|
||||
var
|
||||
tosave : tcpuregisterset;
|
||||
ref : treference;
|
||||
@ -1427,7 +1427,7 @@ unit cgcpu;
|
||||
end;
|
||||
|
||||
|
||||
procedure Tcg68k.g_restore_standard_registers(list:TAsmList);
|
||||
procedure Tcg68k.g_restore_registers(list:TAsmList);
|
||||
var
|
||||
torestore : tcpuregisterset;
|
||||
r:Tregister;
|
||||
|
@ -300,6 +300,9 @@ unit cpubase;
|
||||
}
|
||||
saved_standard_registers : array[0..5] of tsuperregister = (RS_D2,RS_D3,RS_D4,RS_D5,RS_D6,RS_D7);
|
||||
saved_standard_address_registers : array[0..3] of tsuperregister = (RS_A2,RS_A3,RS_A4,RS_A5);
|
||||
|
||||
{ this is only for the generic code which is not used for this architecture }
|
||||
saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{# Required parameter alignment when calling a routine declared as
|
||||
stdcall and cdecl. The alignment value should be the one defined
|
||||
|
@ -353,6 +353,10 @@ unit cpubase;
|
||||
}
|
||||
saved_standard_registers : array[0..8] of tsuperregister =
|
||||
(RS_R16,RS_R17,RS_R18,RS_R19,RS_R20,RS_R21,RS_R22,RS_R23,RS_R30);
|
||||
|
||||
{ this is only for the generic code which is not used for this architecture }
|
||||
saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{ 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.
|
||||
|
@ -2090,7 +2090,7 @@ implementation
|
||||
|
||||
{ oldfpccall expects all registers to be destroyed }
|
||||
if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
|
||||
cg.g_save_standard_registers(list);
|
||||
cg.g_save_registers(list);
|
||||
end;
|
||||
|
||||
|
||||
@ -2102,7 +2102,7 @@ implementation
|
||||
|
||||
{ oldfpccall expects all registers to be destroyed }
|
||||
if current_procinfo.procdef.proccalloption<>pocall_oldfpccall then
|
||||
cg.g_restore_standard_registers(list);
|
||||
cg.g_restore_registers(list);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -78,8 +78,8 @@ unit cgcpu;
|
||||
|
||||
procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
|
||||
procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
|
||||
procedure g_save_standard_registers(list:TAsmList); override;
|
||||
procedure g_restore_standard_registers(list:TAsmList); override;
|
||||
procedure g_save_registers(list:TAsmList); override;
|
||||
procedure g_restore_registers(list:TAsmList); override;
|
||||
|
||||
procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
|
||||
|
||||
@ -857,13 +857,13 @@ const
|
||||
|
||||
{ *********** entry/exit code and address loading ************ }
|
||||
|
||||
procedure tcgppc.g_save_standard_registers(list:TAsmList);
|
||||
procedure tcgppc.g_save_registers(list:TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_entry }
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgppc.g_restore_standard_registers(list:TAsmList);
|
||||
procedure tcgppc.g_restore_registers(list:TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_exit }
|
||||
end;
|
||||
|
@ -348,6 +348,9 @@ uses
|
||||
RS_R30,RS_R31
|
||||
);
|
||||
|
||||
{ this is only for the generic code which is not used for this architecture }
|
||||
saved_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{# 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.
|
||||
|
@ -90,8 +90,8 @@ type
|
||||
boolean); override;
|
||||
procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe:
|
||||
boolean); override;
|
||||
procedure g_save_standard_registers(list: TAsmList); override;
|
||||
procedure g_restore_standard_registers(list: TAsmList); override;
|
||||
procedure g_save_registers(list: TAsmList); override;
|
||||
procedure g_restore_registers(list: TAsmList); override;
|
||||
|
||||
procedure a_loadaddr_ref_reg(list: TAsmList; const ref: treference; r:
|
||||
tregister); override;
|
||||
@ -1275,13 +1275,13 @@ end;
|
||||
|
||||
{ *********** entry/exit code and address loading ************ }
|
||||
|
||||
procedure tcgppc.g_save_standard_registers(list: TAsmList);
|
||||
procedure tcgppc.g_save_registers(list: TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_entry; additionally it is not safe
|
||||
to use it because it is called at some weird time }
|
||||
end;
|
||||
|
||||
procedure tcgppc.g_restore_standard_registers(list: TAsmList);
|
||||
procedure tcgppc.g_restore_registers(list: TAsmList);
|
||||
begin
|
||||
{ this work is done in g_proc_exit; mainly because it is not safe to
|
||||
put the register restore code here because it is called at some weird time }
|
||||
|
@ -348,6 +348,9 @@ const
|
||||
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_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{# 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.
|
||||
|
@ -84,8 +84,8 @@ interface
|
||||
procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
|
||||
procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
|
||||
procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
|
||||
procedure g_restore_standard_registers(list:TAsmList);override;
|
||||
procedure g_save_standard_registers(list : TAsmList);override;
|
||||
procedure g_restore_registers(list:TAsmList);override;
|
||||
procedure g_save_registers(list : TAsmList);override;
|
||||
procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : aint);override;
|
||||
procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : aint);override;
|
||||
procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : aint);
|
||||
@ -1065,7 +1065,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure TCgSparc.g_restore_standard_registers(list:TAsmList);
|
||||
procedure TCgSparc.g_restore_registers(list:TAsmList);
|
||||
begin
|
||||
{ The sparc port uses the sparc standard calling convetions so this function has no used }
|
||||
end;
|
||||
@ -1114,7 +1114,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure TCgSparc.g_save_standard_registers(list : TAsmList);
|
||||
procedure TCgSparc.g_save_registers(list : TAsmList);
|
||||
begin
|
||||
{ The sparc port uses the sparc standard calling convetions so this function has no used }
|
||||
end;
|
||||
|
@ -304,6 +304,9 @@ uses
|
||||
}
|
||||
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_mm_registers : array[0..0] of tsuperregister = (RS_NO);
|
||||
|
||||
{# 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.
|
||||
|
@ -65,24 +65,24 @@ unit cgcpu;
|
||||
if target_info.system=system_x86_64_win64 then
|
||||
begin
|
||||
SetLength(saved_standard_registers,Length(win64_saved_std_regs));
|
||||
SetLength(saved_xmm_registers,Length(win64_saved_xmm_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_xmm_registers[i]:=win64_saved_xmm_regs[i];
|
||||
saved_mm_registers[i]:=win64_saved_xmm_regs[i];
|
||||
end
|
||||
else
|
||||
begin
|
||||
SetLength(saved_standard_registers,Length(others_saved_std_regs));
|
||||
SetLength(saved_xmm_registers,0);
|
||||
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;
|
||||
if assigned(current_procinfo) then
|
||||
framepointer:=getsupreg(current_procinfo.framepointer)
|
||||
framepointer:=getsupreg(current_procinfo.framepointer)
|
||||
else
|
||||
{ in intf. wrapper code generation }
|
||||
framepointer:=RS_FRAME_POINTER_REG;
|
||||
|
@ -123,7 +123,7 @@ const
|
||||
const
|
||||
{ these arrays differ between unix and win64 }
|
||||
saved_standard_registers : array of tsuperregister = nil;
|
||||
saved_xmm_registers : array of tsuperregister = nil;
|
||||
saved_mm_registers : array of tsuperregister = nil;
|
||||
{ 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.
|
||||
@ -132,4 +132,3 @@ const
|
||||
PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
|
||||
}
|
||||
std_param_align = 8;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user