mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-11 04:01:37 +02:00
TOC handling: clean up
Also fix on 32 bits PowerPC
This commit is contained in:
parent
d42f577a3f
commit
629c1de460
@ -1234,7 +1234,7 @@ implementation
|
||||
between code fragments that use a different TOC (which has to be
|
||||
executed when that "branch" returns). So we can't use tail call
|
||||
branches to routines potentially using a different TOC there }
|
||||
if target_info.system in systems_ppc_toc then
|
||||
if target_info.abi in abis_ppc_toc then
|
||||
usehighlevelwrapper:=true
|
||||
else
|
||||
usehighlevelwrapper:=false;
|
||||
|
@ -911,9 +911,17 @@ const
|
||||
end;
|
||||
end;
|
||||
|
||||
{ save the CR if necessary ( !!! never done currently ) }
|
||||
{ still need to find out where this has to be done for SystemV
|
||||
a_reg_alloc(list,R_0);
|
||||
{ save current RTOC for restoration after calls if necessary }
|
||||
if (pi_do_call in current_procinfo.flags) and
|
||||
(target_info.abi in abis_ppc_toc) then
|
||||
begin
|
||||
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||
end;
|
||||
|
||||
{ save the CR if/when we ever start using caller-save portions of that
|
||||
register}
|
||||
{ a_reg_alloc(list,R_0);
|
||||
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
|
||||
list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
|
||||
new_reference(STACK_POINTER_REG,LA_CR)));
|
||||
@ -1306,6 +1314,14 @@ const
|
||||
a_reg_dealloc(list,href.index);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ save current RTOC for restoration after calls if necessary }
|
||||
if pi_do_call in current_procinfo.flags then
|
||||
begin
|
||||
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
|
||||
|
@ -305,22 +305,6 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
function get_rtoc_offset: longint;
|
||||
begin
|
||||
result:=0;
|
||||
case target_info.abi of
|
||||
abi_powerpc_aix,
|
||||
abi_powerpc_darwin:
|
||||
result:=LA_RTOC_AIX;
|
||||
abi_powerpc_elfv1:
|
||||
result:=LA_RTOC_SYSV;
|
||||
abi_powerpc_elfv2:
|
||||
result:=LA_RTOC_ELFV2;
|
||||
else
|
||||
internalerror(2015021001);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ calling a procedure by address }
|
||||
|
||||
procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
|
||||
@ -330,40 +314,44 @@ var
|
||||
begin
|
||||
if (target_info.abi<>abi_powerpc_sysv) then
|
||||
inherited a_call_reg(list,reg)
|
||||
else if (not (cs_opt_size in current_settings.optimizerswitches)) then begin
|
||||
tempreg := getintregister(list, OS_INT);
|
||||
{ load actual function entry (reg contains the reference to the function descriptor)
|
||||
into tempreg }
|
||||
reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
|
||||
else
|
||||
begin
|
||||
if (not (cs_opt_size in current_settings.optimizerswitches)) then
|
||||
begin
|
||||
tempreg := getintregister(list, OS_INT);
|
||||
{ load actual function entry (reg contains the reference to the function descriptor)
|
||||
into tempreg }
|
||||
reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
|
||||
|
||||
{ move actual function pointer to CTR register }
|
||||
list.concat(taicpu.op_reg(A_MTCTR, tempreg));
|
||||
{ move actual function pointer to CTR register }
|
||||
list.concat(taicpu.op_reg(A_MTCTR, tempreg));
|
||||
|
||||
{ load new TOC pointer from function descriptor into RTOC register }
|
||||
reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||
{ load new TOC pointer from function descriptor into RTOC register }
|
||||
reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
||||
|
||||
{ load new environment pointer from function descriptor into R11 register }
|
||||
reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||
a_reg_alloc(list, NR_R11);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
|
||||
{ call function }
|
||||
list.concat(taicpu.op_none(A_BCTRL));
|
||||
a_reg_dealloc(list, NR_R11);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ call ptrgl helper routine which expects the pointer to the function descriptor
|
||||
in R11 }
|
||||
a_reg_alloc(list, NR_R11);
|
||||
a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
|
||||
a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
|
||||
a_reg_dealloc(list, NR_R11);
|
||||
end;
|
||||
{ we need to load the old RTOC from stackframe because we changed it}
|
||||
reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
||||
|
||||
{ load new environment pointer from function descriptor into R11 register }
|
||||
reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||
a_reg_alloc(list, NR_R11);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
|
||||
{ call function }
|
||||
list.concat(taicpu.op_none(A_BCTRL));
|
||||
a_reg_dealloc(list, NR_R11);
|
||||
end else begin
|
||||
{ call ptrgl helper routine which expects the pointer to the function descriptor
|
||||
in R11 }
|
||||
a_reg_alloc(list, NR_R11);
|
||||
a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
|
||||
a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
|
||||
a_reg_dealloc(list, NR_R11);
|
||||
end;
|
||||
|
||||
{ we need to load the old RTOC from stackframe because we changed it}
|
||||
reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
|
||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
||||
|
||||
include(current_procinfo.flags, pi_do_call);
|
||||
end;
|
||||
|
||||
@ -1270,7 +1258,8 @@ begin
|
||||
end;
|
||||
|
||||
{ save current RTOC for restoration after calls if necessary }
|
||||
if pi_do_call in current_procinfo.flags then
|
||||
if (pi_do_call in current_procinfo.flags) and
|
||||
(target_info.abi in abis_ppc_toc) then
|
||||
begin
|
||||
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||
|
@ -89,6 +89,8 @@ unit cgppc;
|
||||
procedure a_jmp(list: TAsmList; op: tasmop;
|
||||
c: tasmcondflag; crval: longint; l: tasmlabel);
|
||||
|
||||
function get_rtoc_offset: longint;
|
||||
|
||||
function save_lr_in_prologue: boolean;
|
||||
|
||||
function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
||||
@ -123,7 +125,6 @@ unit cgppc;
|
||||
C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
|
||||
TocSecBaseName = 'toc_table';
|
||||
|
||||
|
||||
{$ifdef extdebug}
|
||||
function ref2string(const ref : treference) : string;
|
||||
function cgop2string(const op : TOpCg) : String;
|
||||
@ -473,9 +474,6 @@ unit cgppc;
|
||||
{ no need to allocate/free R0, is already allocated by call node
|
||||
because it's a volatile register }
|
||||
reg:=NR_R0;
|
||||
{ save current TOC }
|
||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_AIX,ctempposinvalid,sizeof(pint),[]);
|
||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
|
||||
end;
|
||||
list.concat(taicpu.op_reg(A_MTCTR,reg));
|
||||
if target_info.system in systems_aix then
|
||||
@ -488,9 +486,6 @@ unit cgppc;
|
||||
end
|
||||
else if target_info.abi=abi_powerpc_elfv2 then
|
||||
begin
|
||||
{ save current TOC }
|
||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_ELFV2,ctempposinvalid,sizeof(pint),[]);
|
||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
|
||||
{ functions must be called via R12 for this ABI }
|
||||
if reg<>NR_R12 then
|
||||
begin
|
||||
@ -499,17 +494,13 @@ unit cgppc;
|
||||
end;
|
||||
end;
|
||||
list.concat(taicpu.op_none(A_BCTRL));
|
||||
if (target_info.system in systems_aix) or
|
||||
(target_info.abi=abi_powerpc_elfv2) then
|
||||
if target_info.abi in abis_ppc_toc then
|
||||
begin
|
||||
if (target_info.abi=abi_powerpc_elfv2) and
|
||||
(reg<>NR_R12) then
|
||||
ungetcpuregister(list,NR_R12);
|
||||
{ restore our TOC }
|
||||
if target_info.system in systems_aix then
|
||||
toc_offset:=LA_RTOC_AIX
|
||||
else
|
||||
toc_offset:=LA_RTOC_ELFV2;
|
||||
toc_offset:=get_rtoc_offset;
|
||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
|
||||
a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
|
||||
end;
|
||||
@ -743,6 +734,23 @@ unit cgppc;
|
||||
list.concat(p)
|
||||
end;
|
||||
|
||||
function tcgppcgen.get_rtoc_offset: longint;
|
||||
begin
|
||||
case target_info.abi of
|
||||
abi_powerpc_aix:
|
||||
result:=LA_RTOC_AIX;
|
||||
{$ifdef powerpc64}
|
||||
{ no TOC on Linux/ppc32 }
|
||||
abi_powerpc_elfv1:
|
||||
result:=LA_RTOC_SYSV;
|
||||
{$endif}
|
||||
abi_powerpc_elfv2:
|
||||
result:=LA_RTOC_ELFV2;
|
||||
else
|
||||
internalerror(2015021001);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
||||
|
@ -448,14 +448,9 @@ interface
|
||||
on the caller side rather than on the callee side }
|
||||
systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd];
|
||||
|
||||
{ all PPC systems that use a TOC register to address globals }
|
||||
{ TODO: not used by Darwin, but don't know about others (JM) }
|
||||
systems_ppc_toc = [
|
||||
system_powerpc_linux,
|
||||
system_powerpc64_linux,
|
||||
system_powerpc_aix,
|
||||
system_powerpc64_aix,
|
||||
system_powerpc_macosclassic
|
||||
{ all PPC ABIs that use a TOC register to address globals }
|
||||
abis_ppc_toc = [
|
||||
abi_powerpc_sysv,abi_powerpc_aix,abi_powerpc_elfv2
|
||||
];
|
||||
|
||||
{ pointer checking (requires special code in FPC_CHECKPOINTER,
|
||||
|
Loading…
Reference in New Issue
Block a user