* 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 }
cg.a_reg_dealloc(list,NR_R12);
{$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;

View File

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

View File

@ -300,6 +300,9 @@ const
// Stack pointer register
NR_STACK_POINTER_REG = NR_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
NR_FRAME_POINTER_REG = NR_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 inverse_cond(const c: TAsmCond): Tasmcond;
{$IFDEF USEINLINE}inline;
{$ENDIF USEINLINE}
{$IFDEF USEINLINE}inline;{$ENDIF USEINLINE}
function conditions_equal(const c1, c2: TAsmCond): boolean;
implementation

View File

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

View File

@ -65,14 +65,16 @@ var
locals: longint;
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
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 }
// if (maxpushedparasize < 64) then begin
// maxpushedparasize := 64;
// end;
{ align the stack properly }
ofs := align(maxpushedparasize + LinkageAreaSizeELF, ELF_STACK_ALIGN);
// if (ofs < 112) then begin
// ofs := 112;
// end;
tg.setfirsttemp(ofs);
end else begin
locals := 0;
@ -91,7 +93,7 @@ end;
function tppcprocinfo.calc_stackframe_size: longint;
begin
calc_stackframe_size(18, 18);
result := calc_stackframe_size(18, 18);
end;
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.
}
var
temp : longint;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -51,12 +51,13 @@ asm
.LThreaded:
std r3,temp
mflr r3
std r3,retaddress
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
ori r4, r4, (errno)@highera
sldi r4, r4, 32
oris r4, r4, (errno)@ha
std r3,retaddress
ld r3,(errno)@l(r4)
bctrl
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -99,6 +100,8 @@ asm
std r3,temp
mflr r3
mtctr r10
ld r10, 0(r10)
lis r4, (errno)@highesta
ori r4, r4, (errno)@highera
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -146,6 +149,7 @@ asm
.LThreaded:
std r3,temp
mflr r3
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -196,6 +200,7 @@ asm
.LThreaded:
std r3,temp
mflr r3
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -247,6 +252,7 @@ asm
.LThreaded:
std r3,temp
mflr r3
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -299,6 +305,7 @@ asm
.LThreaded:
std r3,temp
mflr r3
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
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.
}
var
temp : int64;
temp : qword;
retaddress: ptruint;
asm
mr r0,r3
@ -352,6 +359,7 @@ asm
.LThreaded:
std r3,temp
mflr r3
ld r10, 0(r10)
mtctr r10
lis r4, (errno)@highesta
ori r4, r4, (errno)@highera

View File

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

View File

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