* release old stack pointer register on ppc64 after method prolog

* threading fixes for ppc64
* fixed a_param_ref to respect the size parameter on ppc64
* better stack size calculation for ppc64

git-svn-id: trunk@1599 -
This commit is contained in:
tom_at_work 2005-10-26 19:50:17 +00:00
parent f4bb92c0d5
commit c5f89d7efd
8 changed files with 67 additions and 48 deletions

View File

@ -1497,6 +1497,11 @@ implementation
{ which is used to access the parameters in their original callee-side location } { which is used to access the parameters in their original callee-side location }
cg.a_reg_dealloc(list,NR_R12); cg.a_reg_dealloc(list,NR_R12);
{$endif powerpc} {$endif powerpc}
{$ifdef powerpc64}
{ unget the register that contains the stack pointer before the procedure entry, }
{ which is used to access the parameters in their original callee-side location }
cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
{$endif powerpc64}
end; end;

View File

@ -244,8 +244,12 @@ begin
case location^.loc of case location^.loc of
LOC_REGISTER, LOC_CREGISTER: LOC_REGISTER, LOC_CREGISTER:
begin begin
a_load_ref_reg(list, location^.size, location^.size, tmpref, if (size <> OS_NO) then
location^.register); a_load_ref_reg(list, size, location^.size, tmpref,
location^.register)
else
a_load_ref_reg(list, location^.size, location^.size, tmpref,
location^.register)
end; end;
LOC_REFERENCE: LOC_REFERENCE:
begin begin
@ -303,7 +307,7 @@ end;
procedure tcgppc.a_call_name(list: taasmoutput; const s: string); procedure tcgppc.a_call_name(list: taasmoutput; const s: string);
begin begin
a_call_name_direct(list, s, true, true); a_call_name_direct(list, s, true, true);
end; end;
procedure tcgppc.a_call_name_direct(list: taasmoutput; s: string; prependDot : boolean; addNOP : boolean); procedure tcgppc.a_call_name_direct(list: taasmoutput; s: string; prependDot : boolean; addNOP : boolean);
@ -1026,8 +1030,8 @@ begin
end; end;
{ save old stack frame pointer } { save old stack frame pointer }
if (localsize > 0) then begin if (localsize > 0) then begin
a_reg_alloc(list, NR_R12); a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
list.concat(taicpu.op_reg_reg(A_MR, NR_R12, NR_STACK_POINTER_REG)); list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
end; end;
{ save registers, FPU first, then GPR } { save registers, FPU first, then GPR }
reference_reset_base(href, NR_STACK_POINTER_REG, -8); reference_reset_base(href, NR_STACK_POINTER_REG, -8);

View File

@ -300,6 +300,9 @@ const
// Stack pointer register // Stack pointer register
NR_STACK_POINTER_REG = NR_R1; NR_STACK_POINTER_REG = NR_R1;
RS_STACK_POINTER_REG = RS_R1; RS_STACK_POINTER_REG = RS_R1;
// old stack pointer register used during copying variables from the caller
// stack frame
NR_OLD_STACK_POINTER_REG = NR_R12;
// Frame pointer register // Frame pointer register
NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG; NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG;
RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG; RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG;
@ -387,8 +390,7 @@ function std_regname(r: Tregister): string;
function is_condreg(r: tregister): boolean; function is_condreg(r: tregister): boolean;
function inverse_cond(const c: TAsmCond): Tasmcond; function inverse_cond(const c: TAsmCond): Tasmcond;
{$IFDEF USEINLINE}inline; {$IFDEF USEINLINE}inline;{$ENDIF USEINLINE}
{$ENDIF USEINLINE}
function conditions_equal(const c1, c2: TAsmCond): boolean; function conditions_equal(const c1, c2: TAsmCond): boolean;
implementation implementation

View File

@ -97,10 +97,7 @@ begin
end else begin end else begin
loc := LOC_REFERENCE; loc := LOC_REFERENCE;
paraloc^.reference.index := NR_STACK_POINTER_REG; paraloc^.reference.index := NR_STACK_POINTER_REG;
if (target_info.abi <> abi_powerpc_aix) then reference.offset := sizeof(aint) * (nr - 8);
reference.offset := sizeof(aint) * (nr - 8)
else
reference.offset := sizeof(aint) * (nr);
end; end;
end; end;
end; end;
@ -177,10 +174,9 @@ begin
recorddef: recorddef:
result := result :=
((varspez = vs_const) and ((varspez = vs_const) and
((calloption = pocall_mwpascal) or (
(not (calloption in [pocall_cdecl, pocall_cppdecl]) and (not (calloption in [pocall_cdecl, pocall_cppdecl]) and
(def.size > 8) (def.size > 8))
)
) )
); );
arraydef: arraydef:
@ -267,12 +263,12 @@ end;
function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side: function tppcparamanager.create_paraloc_info_intern(p: tabstractprocdef; side:
tcallercallee; paras: tparalist; tcallercallee; paras: tparalist;
var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset:
aword): longint; aword): longint;
var var
stack_offset: longint; stack_offset: longint;
paralen: aint; paralen: aint;
nextintreg, nextfloatreg, nextmmreg, maxfpureg: tsuperregister; nextintreg, nextfloatreg, nextmmreg : tsuperregister;
paradef: tdef; paradef: tdef;
paraloc: pcgparalocation; paraloc: pcgparalocation;
i: integer; i: integer;
@ -292,8 +288,6 @@ begin
nextmmreg := curmmreg; nextmmreg := curmmreg;
stack_offset := cur_stack_offset; stack_offset := cur_stack_offset;
maxfpureg := RS_F13;
for i := 0 to paras.count - 1 do begin for i := 0 to paras.count - 1 do begin
hp := tparavarsym(paras[i]); hp := tparavarsym(paras[i]);
paradef := hp.vartype.def; paradef := hp.vartype.def;
@ -380,9 +374,9 @@ begin
inc(nextintreg); inc(nextintreg);
dec(paralen, tcgsize2size[paraloc^.size]); dec(paralen, tcgsize2size[paraloc^.size]);
inc(stack_offset, tcgsize2size[paraloc^.size]); inc(stack_offset, tcgsize2size[OS_INT]);
end else if (loc = LOC_FPUREGISTER) and end else if (loc = LOC_FPUREGISTER) and
(nextfloatreg <= maxfpureg) then begin (nextfloatreg <= RS_F13) then begin
paraloc^.loc := loc; paraloc^.loc := loc;
paraloc^.size := paracgsize; paraloc^.size := paracgsize;
paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE); paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
@ -391,8 +385,8 @@ begin
inc(nextintreg); inc(nextintreg);
inc(nextfloatreg); inc(nextfloatreg);
dec(paralen, tcgsize2size[paraloc^.size]); dec(paralen, tcgsize2size[paraloc^.size]);
inc(stack_offset, tcgsize2size[paraloc^.size]); inc(stack_offset, tcgsize2size[OS_FLOAT]);
end else if (loc = LOC_MMREGISTER) then begin end else if (loc = LOC_MMREGISTER) then begin
{ Altivec not supported } { Altivec not supported }
internalerror(200510192); internalerror(200510192);
@ -404,11 +398,11 @@ begin
if (side = callerside) then if (side = callerside) then
paraloc^.reference.index := NR_STACK_POINTER_REG paraloc^.reference.index := NR_STACK_POINTER_REG
else else
{ during procedure entry, R12 contains the old stack pointer } { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
paraloc^.reference.index := NR_R12; paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
paraloc^.reference.offset := stack_offset; paraloc^.reference.offset := stack_offset;
{ TODO: change this to the next power of two (natural alignment) } { align temp contents to next register size }
inc(stack_offset, align(paralen, 8)); inc(stack_offset, align(paralen, 8));
paralen := 0; paralen := 0;
end; end;
@ -436,20 +430,16 @@ begin
result := create_paraloc_info_intern(p, callerside, p.paras, curintreg, result := create_paraloc_info_intern(p, callerside, p.paras, curintreg,
curfloatreg, curmmreg, cur_stack_offset); curfloatreg, curmmreg, cur_stack_offset);
if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then if (p.proccalloption in [pocall_cdecl, pocall_cppdecl]) then begin
{ just continue loading the parameters in the registers } { just continue loading the parameters in the registers }
begin
result := create_paraloc_info_intern(p, callerside, varargspara, curintreg, result := create_paraloc_info_intern(p, callerside, varargspara, curintreg,
curfloatreg, curmmreg, cur_stack_offset); curfloatreg, curmmreg, cur_stack_offset);
{ varargs routines have to reserve at least 64 bytes for the AIX abi } { varargs routines have to reserve at least 64 bytes for the PPC64 ABI }
if (result < 64) then if (result < 64) then
result := 64; result := 64;
end end else begin
else
begin
parasize := cur_stack_offset; parasize := cur_stack_offset;
for i := 0 to varargspara.count - 1 do for i := 0 to varargspara.count - 1 do begin
begin
hp := tparavarsym(varargspara[i]); hp := tparavarsym(varargspara[i]);
hp.paraloc[callerside].alignment := 8; hp.paraloc[callerside].alignment := 8;
paraloc := hp.paraloc[callerside].add_location; paraloc := hp.paraloc[callerside].add_location;

View File

@ -65,14 +65,16 @@ var
locals: longint; locals: longint;
begin begin
if not (po_assembler in procdef.procoptions) then begin if not (po_assembler in procdef.procoptions) then begin
{ align the stack properly }
ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
{ the ABI specification says that it is required to always allocate space for 8 * 8 bytes { the ABI specification says that it is required to always allocate space for 8 * 8 bytes
for registers R3-R10 and stack header if there's a stack frame, but GCC doesn't do that, for registers R3-R10 and stack header if there's a stack frame, but GCC doesn't do that,
so we don't that too. Uncomment the next three lines if this is required } so we don't that too. Uncomment the next three lines if this is required }
// if (maxpushedparasize < 64) then begin // if (ofs < 112) then begin
// maxpushedparasize := 64; // ofs := 112;
// end; // end;
{ align the stack properly }
ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
tg.setfirsttemp(ofs); tg.setfirsttemp(ofs);
end else begin end else begin
locals := 0; locals := 0;
@ -91,7 +93,7 @@ end;
function tppcprocinfo.calc_stackframe_size: longint; function tppcprocinfo.calc_stackframe_size: longint;
begin begin
calc_stackframe_size(18, 18); result := calc_stackframe_size(18, 18);
end; end;
function tppcprocinfo.calc_stackframe_size(numgpr, numfpr : longint) : longint; function tppcprocinfo.calc_stackframe_size(numgpr, numfpr : longint) : longint;

View File

@ -28,7 +28,7 @@ function FpSysCall(sysnr:TSysParam):TSysResult; assembler;[public,alias:'FPC_SYS
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : longint; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -51,12 +51,13 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
std r3,retaddress
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
sldi r4, r4, 32 sldi r4, r4, 32
oris r4, r4, (errno)@ha oris r4, r4, (errno)@ha
std r3,retaddress
ld r3,(errno)@l(r4) ld r3,(errno)@l(r4)
bctrl bctrl
ld r4,temp ld r4,temp
@ -74,7 +75,7 @@ function FpSysCall(sysnr,param1:TSysParam):TSysResult; assembler;[public,alias:'
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -99,6 +100,8 @@ asm
std r3,temp std r3,temp
mflr r3 mflr r3
mtctr r10 mtctr r10
ld r10, 0(r10)
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
sldi r4, r4, 32 sldi r4, r4, 32
@ -121,7 +124,7 @@ function FpSysCall(sysnr,param1,param2:TSysParam):TSysResult; assembler;[public,
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -146,6 +149,7 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
@ -170,7 +174,7 @@ function FpSysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; assembler;[
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -196,6 +200,7 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
@ -220,7 +225,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; asse
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -247,6 +252,7 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
@ -271,7 +277,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResul
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -299,6 +305,7 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera
@ -323,7 +330,7 @@ function FpSysCall(sysnr,param1,param2,param3,param4,param5,param6:TSysParam):TS
copies back the registers as they are after the SysCall. copies back the registers as they are after the SysCall.
} }
var var
temp : int64; temp : qword;
retaddress: ptruint; retaddress: ptruint;
asm asm
mr r0,r3 mr r0,r3
@ -352,6 +359,7 @@ asm
.LThreaded: .LThreaded:
std r3,temp std r3,temp
mflr r3 mflr r3
ld r10, 0(r10)
mtctr r10 mtctr r10
lis r4, (errno)@highesta lis r4, (errno)@highesta
ori r4, r4, (errno)@highera ori r4, r4, (errno)@highera

View File

@ -19,7 +19,11 @@
type type
{ fd are int in C also for 64bit targets (x86_64) } { fd are int in C also for 64bit targets (x86_64) }
THandle = Longint; THandle = Longint;
{$ifdef CPUPOWERPC64}
TThreadID = QWord;
{$else}
TThreadID = THandle; TThreadID = THandle;
{$endif}
{ pthread_mutex_t } { pthread_mutex_t }
PRTLCriticalSection = ^TRTLCriticalSection; PRTLCriticalSection = ^TRTLCriticalSection;

View File

@ -93,6 +93,10 @@ Type PINTRTLEvent = ^TINTRTLEvent;
threadvarblocksize:=align(threadvarblocksize,16); threadvarblocksize:=align(threadvarblocksize,16);
{$endif cpux86_64} {$endif cpux86_64}
{$ifdef cpupowerpc64}
threadvarblocksize:=align(threadvarblocksize,16);
{$endif cpupowerpc64}
offset:=threadvarblocksize; offset:=threadvarblocksize;
inc(threadvarblocksize,size); inc(threadvarblocksize,size);