diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas index 8b6282a7ec..59893ecd29 100644 --- a/compiler/powerpc64/cgcpu.pas +++ b/compiler/powerpc64/cgcpu.pas @@ -541,7 +541,7 @@ var tmpref: treference; tempreg : TRegister; begin - if (target_info.system = system_powerpc64_darwin) then + 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 := cg.getintregister(current_asmdata.CurrAsmList, OS_INT); @@ -551,7 +551,7 @@ begin a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg); { save TOC pointer in stackframe } - reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_ELF, 8); + reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_SYSV, 8); a_load_reg_ref(list, OS_ADDR, OS_ADDR, NR_RTOC, tmpref); { move actual function pointer to CTR register } @@ -578,7 +578,7 @@ begin end; { we need to load the old RTOC from stackframe because we changed it} - reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_ELF, 8); + reference_reset_base(tmpref, NR_STACK_POINTER_REG, LA_RTOC_SYSV, 8); a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC); include(current_procinfo.flags, pi_do_call); @@ -1482,7 +1482,7 @@ var { we may need to store R0 (=LR) ourselves } if ((cs_profile in init_settings.moduleswitches) or (mayNeedLRStore)) and (needslinkreg) then begin - reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF, 8); + reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_SYSV, 8); list.concat(taicpu.op_reg_ref(A_STD, NR_R0, href)); end; end; @@ -1620,7 +1620,7 @@ var { restore LR (if needed) } if (needslinkreg) then begin - reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_ELF, 8); + reference_reset_base(href, NR_STACK_POINTER_REG, LA_LR_SYSV, 8); list.concat(taicpu.op_reg_ref(A_LD, NR_R0, href)); list.concat(taicpu.op_reg(A_MTLR, NR_R0)); end; diff --git a/compiler/powerpc64/cpubase.pas b/compiler/powerpc64/cpubase.pas index ecdeba7398..39e31cc3bb 100644 --- a/compiler/powerpc64/cpubase.pas +++ b/compiler/powerpc64/cpubase.pas @@ -366,11 +366,13 @@ const { offset in the linkage area for the saved stack pointer } LA_SP = 0; { offset in the linkage area for the saved conditional register} - LA_CR_ELF = 8; + LA_CR_SYSV = 8; { offset in the linkage area for the saved link register} - LA_LR_ELF = 16; + LA_LR_AIX = 16; + LA_LR_SYSV = 16; { offset in the linkage area for the saved RTOC register} - LA_RTOC_ELF = 40; + LA_RTOC_SYSV = 40; + LA_RTOC_AIX = 40; PARENT_FRAMEPOINTER_OFFSET = 24; diff --git a/compiler/ppcgen/cgppc.pas b/compiler/ppcgen/cgppc.pas index d9e5aa9e4f..423227559d 100644 --- a/compiler/ppcgen/cgppc.pas +++ b/compiler/ppcgen/cgppc.pas @@ -420,9 +420,39 @@ unit cgppc; { calling a procedure by address } procedure tcgppcgen.a_call_reg(list : TAsmList;reg: tregister); + var + tmpref: treference; + tmpreg: tregister; begin + if target_info.system in systems_aix then + begin + { load function address in R0, and swap "reg" for R0 } + reference_reset_base(tmpref,reg,0,sizeof(pint)); + a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_R0); + tmpreg:=reg; + { 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,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 + begin + { load target TOC and possible link register } + reference_reset_base(tmpref,tmpreg,sizeof(pint),sizeof(pint)); + a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC); + tmpref.offset:=2*sizeof(pint); + a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_R11); + end; list.concat(taicpu.op_none(A_BCTRL)); + if target_info.system in systems_aix then + begin + { restore our TOC } + reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_AIX,sizeof(pint)); + a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC); + end; include(current_procinfo.flags,pi_do_call); end;