From 00d6a03b2cabe30bef81d3f7c9e4e852da55176b Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 27 Oct 2007 12:02:28 +0000 Subject: [PATCH] + default code now preserves mm registers * save|restore_standard_registers => save|restore_registers git-svn-id: trunk@8954 - --- compiler/arm/cgcpu.pas | 8 +++--- compiler/arm/cpubase.pas | 4 +++ compiler/cgobj.pas | 52 ++++++++++++++++++++++++++++------ compiler/i386/cpubase.inc | 2 ++ compiler/m68k/cgcpu.pas | 8 +++--- compiler/m68k/cpubase.pas | 3 ++ compiler/mips/cpubase.pas | 4 +++ compiler/ncgutil.pas | 4 +-- compiler/powerpc/cgcpu.pas | 8 +++--- compiler/powerpc/cpubase.pas | 3 ++ compiler/powerpc64/cgcpu.pas | 8 +++--- compiler/powerpc64/cpubase.pas | 3 ++ compiler/sparc/cgcpu.pas | 8 +++--- compiler/sparc/cpubase.pas | 3 ++ compiler/x86_64/cgcpu.pas | 8 +++--- compiler/x86_64/cpubase.inc | 3 +- 16 files changed, 93 insertions(+), 36 deletions(-) diff --git a/compiler/arm/cgcpu.pas b/compiler/arm/cgcpu.pas index 06ed93d016..caa37e9eb5 100644 --- a/compiler/arm/cgcpu.pas +++ b/compiler/arm/cgcpu.pas @@ -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; diff --git a/compiler/arm/cpubase.pas b/compiler/arm/cpubase.pas index bc7bbfeb42..4e5a5978db 100644 --- a/compiler/arm/cpubase.pas +++ b/compiler/arm/cpubase.pas @@ -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. diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index 264414ff14..fb081c6536 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -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; diff --git a/compiler/i386/cpubase.inc b/compiler/i386/cpubase.inc index a7255383c4..e88671c21d 100644 --- a/compiler/i386/cpubase.inc +++ b/compiler/i386/cpubase.inc @@ -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. diff --git a/compiler/m68k/cgcpu.pas b/compiler/m68k/cgcpu.pas index ccc7fcc9c6..28eb425e25 100644 --- a/compiler/m68k/cgcpu.pas +++ b/compiler/m68k/cgcpu.pas @@ -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; diff --git a/compiler/m68k/cpubase.pas b/compiler/m68k/cpubase.pas index 4891ea877f..3a7a743890 100644 --- a/compiler/m68k/cpubase.pas +++ b/compiler/m68k/cpubase.pas @@ -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 diff --git a/compiler/mips/cpubase.pas b/compiler/mips/cpubase.pas index fb8177b8a9..e98cf90cfa 100644 --- a/compiler/mips/cpubase.pas +++ b/compiler/mips/cpubase.pas @@ -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. diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 96040eb168..a1b169f666 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -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; diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas index 56801ac00f..1c524c5b3d 100644 --- a/compiler/powerpc/cgcpu.pas +++ b/compiler/powerpc/cgcpu.pas @@ -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; diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas index c33a509f21..aa1ef95d41 100644 --- a/compiler/powerpc/cpubase.pas +++ b/compiler/powerpc/cpubase.pas @@ -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. diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas index e33f288a0a..1cfae1590f 100644 --- a/compiler/powerpc64/cgcpu.pas +++ b/compiler/powerpc64/cgcpu.pas @@ -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 } diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas index 7768acbdea..b48a73bbdd 100644 --- a/compiler/powerpc64/cpubase.pas +++ b/compiler/powerpc64/cpubase.pas @@ -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. diff --git a/compiler/sparc/cgcpu.pas b/compiler/sparc/cgcpu.pas index f1be3bff98..b750225e46 100644 --- a/compiler/sparc/cgcpu.pas +++ b/compiler/sparc/cgcpu.pas @@ -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; diff --git a/compiler/sparc/cpubase.pas b/compiler/sparc/cpubase.pas index 8086ec5ecb..73e7837244 100644 --- a/compiler/sparc/cpubase.pas +++ b/compiler/sparc/cpubase.pas @@ -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. diff --git a/compiler/x86_64/cgcpu.pas b/compiler/x86_64/cgcpu.pas index 121be125f4..e28620fca8 100644 --- a/compiler/x86_64/cgcpu.pas +++ b/compiler/x86_64/cgcpu.pas @@ -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; diff --git a/compiler/x86_64/cpubase.inc b/compiler/x86_64/cpubase.inc index 90c1fe3a24..bb535eaf75 100644 --- a/compiler/x86_64/cpubase.inc +++ b/compiler/x86_64/cpubase.inc @@ -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; -