mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 15:29:25 +02:00
powerpc: reworked syscall generation once more. instead of making various assumptions on the syscallib location based on the calling convention, simply search for the lib and use its location. also unified the call generation itself
git-svn-id: trunk@34435 -
This commit is contained in:
parent
95520ea767
commit
7a6f18c496
@ -43,7 +43,7 @@ implementation
|
||||
uses
|
||||
globtype,systems,
|
||||
cutils,verbose,globals,
|
||||
symconst,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
|
||||
symconst,symtype,symbase,symsym,symcpu,symtable,defutil,paramgr,parabase,
|
||||
cgbase,pass_2,
|
||||
cpuinfo,cpubase,aasmbase,aasmtai,aasmdata,aasmcpu,
|
||||
nmem,nld,ncnv,
|
||||
@ -71,23 +71,28 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure tppccallnode.do_syscall;
|
||||
|
||||
procedure do_call_ref(constref ref: treference);
|
||||
begin
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,ref,NR_R0);
|
||||
cg.a_call_reg(current_asmdata.CurrAsmList,NR_R0);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
end;
|
||||
|
||||
var
|
||||
tmpref: treference;
|
||||
libparaloc: pcgparalocation;
|
||||
hsym: tsym;
|
||||
begin
|
||||
case target_info.system of
|
||||
system_powerpc_amiga:
|
||||
begin
|
||||
// one syscall convention for Amiga/PowerPC
|
||||
// which is very similar to basesysv on MorphOS
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
{ one syscall convention for AmigaOS/PowerPC
|
||||
which is very similar to basesysv on MorphOS }
|
||||
reference_reset_base(tmpref,NR_R3,tprocdef(procdefinition).extnumber,sizeof(pint));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
do_call_ref(tmpref);
|
||||
end;
|
||||
system_powerpc_morphos:
|
||||
begin
|
||||
@ -95,54 +100,42 @@ implementation
|
||||
if ([po_syscall_basesysv,po_syscall_sysv,
|
||||
po_syscall_sysvbase,po_syscall_r12base] * tprocdef(procdefinition).procoptions) <> [] then
|
||||
begin
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
|
||||
|
||||
if (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then
|
||||
begin
|
||||
{ for sysvbase, find the last para, and get the libbase from there }
|
||||
libparaloc:=paralocs[procdefinition.paras.count-1]^.location;
|
||||
if libparaloc^.loc = LOC_REGISTER then
|
||||
reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint))
|
||||
else if libparaloc^.loc = LOC_REFERENCE then
|
||||
begin
|
||||
reference_reset_base(tmpref,libparaloc^.reference.index,libparaloc^.reference.offset,sizeof(pint));
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,NR_R12);
|
||||
reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
|
||||
end
|
||||
else
|
||||
internalerror(2016090202);
|
||||
end
|
||||
else
|
||||
if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then
|
||||
reference_reset_base(tmpref,NR_R3,-tprocdef(procdefinition).extnumber,sizeof(pint))
|
||||
hsym:=tsym(procdefinition.parast.Find('syscalllib'));
|
||||
if not assigned(hsym) then
|
||||
internalerror(2016090501);
|
||||
libparaloc:=tparavarsym(hsym).paraloc[callerside].location;
|
||||
if not assigned(libparaloc) then
|
||||
internalerror(2016090502);
|
||||
|
||||
case libparaloc^.loc of
|
||||
LOC_REGISTER:
|
||||
reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint));
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
{ this can happen for sysvbase; if we run out of regs, the libbase will be passed on the stack }
|
||||
reference_reset_base(tmpref,libparaloc^.reference.index,libparaloc^.reference.offset,sizeof(pint));
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpref,NR_R12);
|
||||
reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
|
||||
end;
|
||||
else
|
||||
{ other calling conventions expect the base in R12 at this point }
|
||||
reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
|
||||
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
|
||||
internalerror(2016090202);
|
||||
end;
|
||||
|
||||
do_call_ref(tmpref);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
end
|
||||
else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
|
||||
begin
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R3);
|
||||
|
||||
{ store call offset into R3 }
|
||||
{ R3 must contain the call offset }
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_const(A_LI,NR_R3,-tprocdef(procdefinition).extnumber));
|
||||
|
||||
{ prepare LR, and call function }
|
||||
reference_reset_base(tmpref,NR_R2,100,4); { 100 ($64) is EmulDirectCallOS offset }
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R0,tmpref));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTLR,NR_R0));
|
||||
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BLRL));
|
||||
|
||||
do_call_ref(tmpref);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R3);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
|
||||
end
|
||||
else
|
||||
internalerror(2005010403);
|
||||
|
Loading…
Reference in New Issue
Block a user