mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 13:08:49 +02:00
* 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:
parent
f4bb92c0d5
commit
c5f89d7efd
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user