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:
Károly Balogh 2016-09-05 21:11:51 +00:00
parent 95520ea767
commit 7a6f18c496

View File

@ -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);