powerpc: simplified code generation for MorphOS syscalls

git-svn-id: trunk@34417 -
This commit is contained in:
Károly Balogh 2016-09-03 07:58:17 +00:00
parent 464ecab542
commit 84abdd8287
2 changed files with 45 additions and 65 deletions

View File

@ -664,8 +664,10 @@ unit cpupara;
var var
paraloc : pcgparalocation; paraloc : pcgparalocation;
paracgsize : tcgsize; paracgsize : tcgsize;
offset : aint;
begin begin
result:=false; result:=false;
offset:=-1;
case target_info.system of case target_info.system of
system_powerpc_morphos: system_powerpc_morphos:
begin begin
@ -674,58 +676,34 @@ unit cpupara;
p.paraloc[callerside].size:=paracgsize; p.paraloc[callerside].size:=paracgsize;
p.paraloc[callerside].intsize:=tcgsize2size[paracgsize]; p.paraloc[callerside].intsize:=tcgsize2size[paracgsize];
paraloc:=p.paraloc[callerside].add_location; paraloc:=p.paraloc[callerside].add_location;
paraloc^.loc:=LOC_REFERENCE;
{ The OS side should be zero extended and the entire "virtual" { The OS side should be zero extended and the entire "virtual"
68k register should be overwritten. This is what the C ppcinline 68k register should be overwritten. This is what the C ppcinline
macros do as well, by casting all arguments to ULONG. A call macros do as well, by casting all arguments to ULONG. A call
which breaks w/o this is for example exec/RawPutChar (KB) } which breaks w/o this is for example exec/RawPutChar (KB) }
paraloc^.size:=OS_ADDR; paraloc^.size:=OS_ADDR;
paraloc^.def:=p.vardef; paraloc^.def:=p.vardef;
paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
{ pattern is always uppercase'd } { convert d0-d7/a0-a6 virtual 68k reg patterns into offsets }
if s='D0' then if length(s) = 2 then
paraloc^.reference.offset:=0 begin
else if s='D1' then if (s[1] = 'D') and (s[2] in ['0'..'7']) then
paraloc^.reference.offset:=4 offset:=(ord(s[2]) - ord('0')) * sizeof(pint)
else if s='D2' then else if (s[1] = 'A') and (s[2] in ['0'..'6']) then
paraloc^.reference.offset:=8 offset:=(ord(s[2]) - ord('0') + 8) * sizeof(pint);
else if s='D3' then
paraloc^.reference.offset:=12 if offset < 0 then
else if s='D4' then exit;
paraloc^.reference.offset:=16
else if s='D5' then paraloc^.loc:=LOC_REFERENCE;
paraloc^.reference.offset:=20 paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
else if s='D6' then paraloc^.reference.offset:=offset;
paraloc^.reference.offset:=24 end
else if s='D7' then { 'R12' is special, used internally to support r12base and sysv
paraloc^.reference.offset:=28
else if s='A0' then
paraloc^.reference.offset:=32
else if s='A1' then
paraloc^.reference.offset:=36
else if s='A2' then
paraloc^.reference.offset:=40
else if s='A3' then
paraloc^.reference.offset:=44
else if s='A4' then
paraloc^.reference.offset:=48
else if s='A5' then
paraloc^.reference.offset:=52
{ 'A6' (offset 56) is used by mossyscall as libbase, so API
never passes parameters in it,
Indeed, but this allows to declare libbase either explicitly
or let the compiler insert it }
else if s='A6' then
paraloc^.reference.offset:=56
{ 'A7' is the stack pointer on 68k, can't be overwritten
by API calls, so it has no offset }
{ 'R12' is special, used internally to support r12base sysv
calling convention } calling convention }
else if s='R12' then else if s='R12' then
begin begin
paraloc^.loc:=LOC_REGISTER; paraloc^.loc:=LOC_REGISTER;
paraloc^.size:=OS_ADDR;
paraloc^.def:=voidpointertype;
paraloc^.register:=NR_R12; paraloc^.register:=NR_R12;
end end
else else

View File

@ -75,6 +75,7 @@ implementation
procedure tppccallnode.do_syscall; procedure tppccallnode.do_syscall;
var var
tmpref: treference; tmpref: treference;
libparaloc: pcgparalocation;
begin begin
case target_info.system of case target_info.system of
system_powerpc_amiga: system_powerpc_amiga:
@ -90,21 +91,35 @@ implementation
end; end;
system_powerpc_morphos: system_powerpc_morphos:
begin begin
if (po_syscall_sysv in tprocdef(procdefinition).procoptions) or { all conventions but legacy }
(po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then if ([po_syscall_basesysv,po_syscall_sysv,
po_syscall_sysvbase,po_syscall_r12base] * tprocdef(procdefinition).procoptions) <> [] then
begin begin
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12); cg.getcpuregister(current_asmdata.CurrAsmList,NR_R12);
reference_reset(tmpref,sizeof(pint)); if (po_syscall_sysvbase in tprocdef(procdefinition).procoptions) then
tmpref.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(tcpuprocdef(procdefinition).libsym).mangledname,AT_DATA); begin
tmpref.refaddr:=addr_higha; { for sysvbase, find the last para, and get the libbase from there }
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LIS,NR_R12,tmpref)); libparaloc:=paralocs[procdefinition.paras.count-1]^.location;
tmpref.base:=NR_R12; if libparaloc^.loc = LOC_REGISTER then
tmpref.refaddr:=addr_low; reference_reset_base(tmpref,libparaloc^.register,-tprocdef(procdefinition).extnumber,sizeof(pint))
current_asmdata.CurrAsmList.concat(taicpu.op_reg_ref(A_LWZ,NR_R12,tmpref)); 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))
else
{ other calling conventions expect the base in R12 at this point }
reference_reset_base(tmpref,NR_R12,-tprocdef(procdefinition).extnumber,sizeof(pint));
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_ref(A_LWZ,NR_R0,tmpref));
current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0)); current_asmdata.CurrAsmList.concat(taicpu.op_reg(A_MTCTR,NR_R0));
current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL)); current_asmdata.CurrAsmList.concat(taicpu.op_none(A_BCTRL));
@ -112,19 +127,6 @@ implementation
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12); cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R12);
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
end end
else if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) or
(po_syscall_r12base in tprocdef(procdefinition).procoptions) then
begin
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
if (po_syscall_basesysv in tprocdef(procdefinition).procoptions) then
reference_reset_base(tmpref,NR_R3,-tprocdef(procdefinition).extnumber,sizeof(pint))
else
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));
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
end
else if po_syscall_legacy in tprocdef(procdefinition).procoptions then else if po_syscall_legacy in tprocdef(procdefinition).procoptions then
begin begin
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);